<template>
  <el-container>
    <el-aside width="300px" v-loading="menuLoading">
      <el-container>
        <el-header>
          <el-input placeholder="输入关键字进行过滤" v-model="menuFilterText" clearable></el-input>
        </el-header>
        <el-main class="nopadding">
          <el-tree ref="menu" class="menu" node-key="id" :data="menuList" :props="menuProps" draggable highlight-current
            :expand-on-click-node="false" :default-expanded-keys="expandedKeys" check-strictly show-checkbox
            :filter-node-method="menuFilterNode" @node-click="menuClick" @node-drop="nodeDrop">

            <template #default="{node, data}">
              <span class="custom-tree-node">
                <span class="label">
                  {{ node.label }}
                </span>
                <span class="do">
                  <el-button :icon="Plus" size="small" @click.stop="add(node, data)">添加</el-button>
                </span>
              </span>
            </template>

          </el-tree>
        </el-main>
        <el-footer style="height:51px;">
          <el-button type="primary" size="small" :icon="Plus" @click="add()">添加</el-button>
          <el-button type="danger" size="small" plain :icon="Delete" @click="delMenu">删除</el-button>
        </el-footer>
      </el-container>
    </el-aside>
    <el-container>
      <el-main class="nopadding" style="padding:20px;" ref="main">
        <save-view ref="save" :menu="menuList" @success="handleSaveSuccess"></save-view>
      </el-main>
    </el-container>
  </el-container>
</template>

<script setup>
import { ref, watch, onMounted, toRaw } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, Plus } from '@element-plus/icons-vue'
import http from "@/utils/request.js";
import saveView from './save.vue'

let newMenuIndex = 1
const route = useRoute()

// refs
const menu = ref(null)
const save = ref(null)
const main = ref(null)

// reactive data
const loading = ref(false)
const menuLoading = ref(false)



const menuList = ref([])
const menuProps = {
  label: (data) => {
    return data.name
  }
}
const expandedKeys = ref([])
const menuFilterText = ref('')
const selectId = ref('')
const selectData = ref('')
const searchObject = ref({
  app: '',
  fetch:1,
  depth:1,
  sortMethod:"asc",
  sortField:"sortNum"
})

// watch
watch(menuFilterText, (val) => {
  menu.value.filter(val)
})

// methods
const handleSaveSuccess = async () => {
  await getMenu()
  // 恢复选中状态
}

const getMenu = async () => {
  menuLoading.value = true
  const res = await http.post("/appMenu/list", searchObject.value)
  if (res.code === 0) {
    tableData.value = res
  }
  loading.value = false
  menuLoading.value = false
  menuList.value = res.data
}

const menuClick = (data, node) => {
  if (!save.value) {
    console.error('save component is not ready')
    return
  }
  const pid = node.level === 1 ? undefined : node.parent.data.id
  const menuData = {
    id: data.id,
    name: data.name,
    icon: data.icon,
    router: data.router,
    sortNum: data.sortNum,
    title: data.name,
    permission: data.permission
  }
  save.value.setData(menuData, pid)
}

const menuFilterNode = (value, data) => {
  if (!value) return true
  const targetText = data.name
  return targetText.indexOf(value) !== -1
}

const nodeDrop = async (draggingNode, dropNode, dropType) => {
  save.value.setData({})
  console.info(dropType)
  console.info(draggingNode)
  console.info(dropNode)

  if (dropType === "inner") {
    console.info(draggingNode.data.id + " " + draggingNode.data.label)
    console.info(dropNode.data.id + " " + dropNode.data.label)
    const param = {
      id: draggingNode.data.id,
      parent: dropNode.data.id
    }
    await http.post("/appMenu/update", param)
  } else if (dropType === "inner") {
    console.info(draggingNode.data.id + " " + draggingNode.data.label)
    console.info(dropNode.data.id + " " + dropNode.data.label)

    const param = {
      id: draggingNode.data.id,
      sortNum: dropNode.data.sortNum
    }
    await http.post("/appMenu/update", param)

    const param1 = {
      id: dropNode.data.id,
      sortNum: draggingNode.data.sortNum
    }
    await http.post("/appMenu/update", param1)
  } else {
    console.info(draggingNode.data.id + " " + draggingNode.data.label)
    console.info(dropNode.data.id + " " + dropNode.data.label)

    const param = {
      menu: draggingNode.data.id,
      target: dropNode.data.id,
      dropType: dropType
    }
    await http.post("/appMenu/drag", param)
  }
}

const add = async (node, data) => {
  const newMenuName = "未命名" + newMenuIndex++
  let newMenuData = {
    parent: data ? data.id : "",
    name: newMenuName,
    path: "",
    component: "",
    meta: {
      title: newMenuName,
      type: "menu"
    }
  }
  newMenuData.app = searchObject.value.app
  menuLoading.value = true
  try {
    const res = await http.post("/appMenu/create", newMenuData)
    if(res.code !== 200){
      ElMessage.error(res.message || '创建失败')
      return
    }
    newMenuData = res.data
    // 服务端创建成功后，将新节点添加到树中
    menu.value.append(newMenuData, node)
    menu.value.setCurrentKey(newMenuData.id)
    const pid = node ? node.data.id : ""
    // 先设置选中状态
    selectId.value = newMenuData.id
    selectData.value = node
    // 然后设置表单数据
    save.value.setData(newMenuData, pid)
  } catch (error) {
    ElMessage.error('创建失败：' + error.message)
  } finally {
    menuLoading.value = false
  }
}

const delMenu = async () => {
  const CheckedNodes = menu.value.getCheckedNodes()
  if (CheckedNodes.length == 0) {
    ElMessage.warning("请选择需要删除的项")
    return false
  }

  const confirm = await ElMessageBox.confirm('确认删除已选择的菜单吗？', '提示', {
    type: 'warning',
    confirmButtonText: '删除',
    confirmButtonClass: 'el-button--danger'
  }).catch(() => {})

  if (confirm !== 'confirm') {
    return false
  }

  menuLoading.value = true
  const reqData = {
    ids: CheckedNodes.map(item => item.id)
  }
  let res = null
  for (let i = 0; i < reqData.ids.length; i++) {
    const item = reqData.ids[i]
    res = await http.post("/appMenu/delete", { id: item })
  }
  menuLoading.value = false

  if (res.code === 200) {
    CheckedNodes.forEach(item => {
      const node = menu.value.getNode(item)
      if (node.isCurrent) {
        save.value.setData({})
      }
      menu.value.remove(item)
    })
  } else {
    ElMessage.warning(res.message)
  }
}

// mounted
onMounted(() => {
  searchObject.value.app = route.query.id
  getMenu()
})
</script>

<style scoped>
.menu:deep(.el-tree-node__label) {
  display: flex;
  flex: 1;
  height: 100%;
}

.custom-tree-node {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  height: 100%;
  padding-right: 24px;
}

.custom-tree-node .label {
  display: flex;
  align-items: center;;
  height: 100%;
}

.custom-tree-node .label .el-tag {
  margin-left: 5px;
}

.custom-tree-node .do {
  display: none;
}

.custom-tree-node .do i {
  margin-left: 5px;
  color: #999;
}

.custom-tree-node .do i:hover {
  color: #333;
}

.custom-tree-node:hover .do {
  display: inline-block;
}
</style>
